package com.jlpay.open.jlpay.sdk.java.service;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jlpay.open.jlpay.sdk.java.config.OrgConfig;
import com.jlpay.open.jlpay.sdk.java.exception.HttpExecutionException;
import com.jlpay.open.jlpay.sdk.java.exception.HttpStatusCodeException;
import com.jlpay.open.jlpay.sdk.java.exception.KeyInitializationException;
import com.jlpay.open.jlpay.sdk.java.exception.SignVerifyException;
import com.jlpay.open.jlpay.sdk.java.http.DefaultHttpClientBuilder;
import com.jlpay.open.jlpay.sdk.java.http.HttpClient;
import com.jlpay.open.jlpay.sdk.java.http.JlpayHttpHeaders;
import com.jlpay.open.jlpay.sdk.java.http.MultipartHttpRequest;
import com.jlpay.open.jlpay.sdk.java.model.upload.request.UploadBaseReq;
import com.jlpay.open.jlpay.sdk.java.utils.HttpUtils;
import com.jlpay.open.jlpay.sdk.java.utils.json.JsonUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/***
 * 嘉联支付文件上传服务
 * @author xuexiaoya
 * @date 2024/3/4
 **/
public class JlpayUploadFileService {

    private final HttpClient httpClient;

    private final OrgConfig config;

    private JlpayUploadFileService(HttpClient httpClient, OrgConfig config) {
        this.httpClient = Objects.requireNonNull(httpClient, "httpClient is required");
        this.config = Objects.requireNonNull(config, "config is required");
    }

    /**
     * 发送 POST 请求
     *
     * @param request       机构请求参数
     * @param responseClass 返回参数类型
     * @param <T>           返回参数类型
     * @return 响应对象
     * @throws IllegalArgumentException   请求参数错误
     * @throws HttpExecutionException     请求发送失败
     * @throws HttpStatusCodeException    响应状态码不在200~300之间
     * @throws KeyInitializationException 密钥初始化失败
     * @throws SignVerifyException        签名/验签失败
     */
    public <T> T post(UploadBaseReq request, Class<T> responseClass) {
        Objects.requireNonNull(request, "request is required");
        ObjectNode meta = JsonUtils.createObjectNode();
        meta.put("filename", request.getFileName());
        meta.put("alg", request.getAlg().getValue());
        MultipartHttpRequest postRequest = MultipartHttpRequest.builder()
                .url(HttpUtils.parseUrl(config.getUrl() + request.path()))
                .headers(buildHeaders(request))
                .meta(meta)
                .file(request.getFile())
                .build();
        postRequest.setUrl(HttpUtils.parseUrl(config.getUrl() + request.path()));
        postRequest.setHeaders(buildHeaders(request));
        postRequest.setMeta(meta);
        postRequest.setFile(request.getFile());
        return httpClient.postForm(postRequest, responseClass);
    }


    private Map<String, String> buildHeaders(UploadBaseReq request) {
        Map<String, String> headers = new HashMap<>();
        headers.put(JlpayHttpHeaders.CONTENT_TYPE, JlpayHttpHeaders.MediaType.MULTIPART_FORM_DATA_VALUE);
        headers.put(JlpayHttpHeaders.ACCEPT, JlpayHttpHeaders.MediaType.APPLICATION_JSON_UTF8);
        headers.put(JlpayHttpHeaders.V5.APP_ID, config.getAppId());
        return headers;
    }

    public static class Builder {

        private HttpClient httpClient;

        private OrgConfig config;

        public Builder config(OrgConfig config) {
            this.config = config;
            return this;
        }

        public Builder httpClient(HttpClient httpClient) {
            this.httpClient = httpClient;
            return this;
        }

        public JlpayUploadFileService build() {
            Objects.requireNonNull(config, "config is required");
            if (httpClient == null) {
                httpClient = new DefaultHttpClientBuilder()
                        .config(config)
                        .build();
            }
            return new JlpayUploadFileService(httpClient, config);
        }
    }

}
